home *** CD-ROM | disk | FTP | other *** search
/ Ham Radio 2000 / Ham Radio 2000.iso / ham2000 / tcp_ip / tnos / tnos100s / domhdr.c < prev    next >
C/C++ Source or Header  |  1993-04-30  |  12KB  |  499 lines

  1. /* Domain header conversion routines
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  * Additional support for the Domain Name Server
  5.  * by Johan. K. Reinalda, WG7J,
  6.  * based on previous work by Gerard v.d. Grinten, PA0GRI
  7.  */
  8. #include "global.h"
  9. #include "config.h"
  10. #include "mbuf.h"
  11. #include "domain.h"
  12.  
  13. static int dn_expand __ARGS((char *msg,char *eom,char *compressed,char *full,
  14.     int fullen));
  15. static char *getq __ARGS((struct rr **rrpp,char *msg,char *cp));
  16. static char *ntohrr __ARGS((struct rr **rrpp,char *msg,char *cp));
  17.  
  18. int
  19. ntohdomain(dhdr,bpp)
  20. register struct dhdr *dhdr;
  21. struct mbuf **bpp;
  22. {
  23.     int16 tmp,len;
  24.     register int16 i;
  25.     char *msg,*cp;
  26.     struct rr **rrpp;
  27.  
  28.     len = len_p(*bpp);
  29.     msg = mallocw(len);
  30.     pullup(bpp,msg,len);
  31.     memset((char *)dhdr,0,sizeof(*dhdr));
  32.  
  33.     dhdr->id = get16(&msg[0]);
  34.     tmp = get16(&msg[2]);
  35.     if(tmp & 0x8000)
  36.         dhdr->qr = 1;
  37.     dhdr->opcode = (tmp >> 11) & 0xf;
  38.     if(tmp & 0x0400)
  39.         dhdr->aa = 1;
  40.     if(tmp & 0x0200)
  41.         dhdr->tc = 1;
  42.     if(tmp & 0x0100)
  43.         dhdr->rd = 1;
  44.     if(tmp & 0x0080)
  45.         dhdr->ra = 1;
  46.     dhdr->rcode = tmp & 0xf;
  47.     dhdr->qdcount = get16(&msg[4]);
  48.     dhdr->ancount = get16(&msg[6]);
  49.     dhdr->nscount = get16(&msg[8]);
  50.     dhdr->arcount = get16(&msg[10]);
  51.  
  52.     /* Now parse the variable length sections */
  53.     cp = &msg[12];
  54.  
  55.     /* Question section */
  56.     rrpp = &dhdr->questions;
  57.     for(i=0;i<dhdr->qdcount;i++){
  58.         if((cp = getq(rrpp,msg,cp)) == NULLCHAR){
  59.             free(msg);
  60.             return -1;
  61.         }
  62.         (*rrpp)->source = RR_QUESTION;
  63.         rrpp = &(*rrpp)->next;
  64.     }
  65.     *rrpp = NULLRR;
  66.  
  67.     /* Answer section */
  68.     rrpp = &dhdr->answers;
  69.     for(i=0;i<dhdr->ancount;i++){
  70.         if((cp = ntohrr(rrpp,msg,cp)) == NULLCHAR){
  71.             free(msg);
  72.             return -1;
  73.         }
  74.         (*rrpp)->source = RR_ANSWER;
  75.         rrpp = &(*rrpp)->next;
  76.     }
  77.     *rrpp = NULLRR;
  78.  
  79.     /* Name server (authority) section */
  80.     rrpp = &dhdr->authority;
  81.     for(i=0;i<dhdr->nscount;i++){
  82.         if((cp = ntohrr(rrpp,msg,cp)) == NULLCHAR){
  83.             free(msg);
  84.             return -1;
  85.         }
  86.         (*rrpp)->source = RR_AUTHORITY;
  87.         rrpp = &(*rrpp)->next;
  88.     }
  89.     *rrpp = NULLRR;
  90.  
  91.     /* Additional section */
  92.     rrpp = &dhdr->additional;
  93.     for(i=0;i<dhdr->arcount;i++){
  94.         if((cp = ntohrr(rrpp,msg,cp)) == NULLCHAR){
  95.             free(msg);
  96.             return -1;
  97.         }
  98.         (*rrpp)->source = RR_ADDITIONAL;
  99.         rrpp = &(*rrpp)->next;
  100.     }
  101.     *rrpp = NULLRR;
  102.     free(msg);
  103.     return 0;
  104. }
  105. static char *
  106. getq(rrpp,msg,cp)
  107. struct rr **rrpp;
  108. char *msg;
  109. char *cp;
  110. {
  111.     register struct rr *rrp;
  112.     int len;
  113.     char *name;
  114.  
  115.     *rrpp = rrp = (struct rr *)callocw(1,sizeof(struct rr));
  116.     name = mallocw(512);
  117.     len = dn_expand(msg,NULLCHAR,cp,name,512);
  118.     if(len == -1){
  119.         free(name);
  120.         return NULLCHAR;
  121.     }
  122.     cp += len;
  123.     rrp->name = strdup(name);
  124.     rrp->type = get16(cp);
  125.     cp += 2;
  126.     rrp->class = get16(cp);
  127.     cp += 2;
  128.     rrp->ttl = 0;
  129.     rrp->rdlength = 0;
  130.     free(name);
  131.     return cp;
  132. }
  133. /* Read a resource record from a domain message into a host structure */
  134. static char *
  135. ntohrr(rrpp,msg,cp)
  136. struct rr **rrpp; /* Where to allocate resource record structure */
  137. char *msg;    /* Pointer to beginning of domain message */
  138. char *cp;    /* Pointer to start of encoded RR record */
  139. {
  140.     register struct rr *rrp;
  141.     int len;
  142.     char *name;
  143.  
  144.     *rrpp = rrp = (struct rr *)callocw(1,sizeof(struct rr));
  145.     name = mallocw(512);
  146.     if((len = dn_expand(msg,NULLCHAR,cp,name,512)) == -1){
  147.         free(name);
  148.         return NULLCHAR;
  149.     }
  150.     cp += len;
  151.     rrp->name = strdup(name);
  152.     rrp->type = get16(cp);
  153.     cp += 2;
  154.     rrp->class = get16(cp);
  155.     cp+= 2;
  156.     rrp->ttl = get32(cp);
  157.     cp += 4;
  158.     rrp->rdlength = get16(cp);
  159.     cp += 2;
  160.     switch(rrp->type){
  161.     case TYPE_A:
  162.         /* Just read the address directly into the structure */
  163.         rrp->rdata.addr = get32(cp);
  164.         cp += 4;
  165.         break;
  166.     case TYPE_CNAME:
  167.     case TYPE_MB:
  168.     case TYPE_MG:
  169.     case TYPE_MR:
  170.     case TYPE_NS:
  171.     case TYPE_PTR:
  172.         /* These types all consist of a single domain name;
  173.          * convert it to ascii format
  174.          */
  175.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  176.         if(len == -1){
  177.             free(name);
  178.             return NULLCHAR;
  179.         }
  180.         rrp->rdata.name = strdup(name);
  181.         rrp->rdlength = strlen(name);
  182.         cp += len;
  183.         break;
  184.     case TYPE_HINFO:
  185.         len = *cp++;
  186.         rrp->rdata.hinfo.cpu = mallocw(len+1);
  187.         memcpy( rrp->rdata.hinfo.cpu, cp, len );
  188.         rrp->rdata.hinfo.cpu[len] = '\0';
  189.         cp += len;
  190.  
  191.         len = *cp++;
  192.         rrp->rdata.hinfo.os = mallocw(len+1);
  193.         memcpy( rrp->rdata.hinfo.os, cp, len );
  194.         rrp->rdata.hinfo.os[len] = '\0';
  195.         cp += len;
  196.         break;
  197.     case TYPE_MX:
  198.         rrp->rdata.mx.pref = get16(cp);
  199.         cp += 2;
  200.         /* Get domain name of exchanger */
  201.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  202.         if(len == -1){
  203.             free(name);
  204.             return NULLCHAR;
  205.         }
  206.         rrp->rdata.mx.exch = strdup(name);
  207.         cp += len;
  208.         break;
  209.     case TYPE_SOA:
  210.         /* Get domain name of name server */
  211.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  212.         if(len == -1){
  213.             free(name);
  214.             return NULLCHAR;
  215.         }
  216.         rrp->rdata.soa.mname = strdup(name);
  217.         cp += len;
  218.  
  219.         /* Get domain name of responsible person */
  220.         len = dn_expand(msg,NULLCHAR,cp,name,512);
  221.         if(len == -1){
  222.             free(name);
  223.             return NULLCHAR;
  224.         }
  225.         rrp->rdata.soa.rname = strdup(name);
  226.         cp += len;
  227.  
  228.         rrp->rdata.soa.serial = get32(cp);
  229.         cp += 4;
  230.         rrp->rdata.soa.refresh = get32(cp);
  231.         cp += 4;
  232.         rrp->rdata.soa.retry = get32(cp);
  233.         cp += 4;
  234.         rrp->rdata.soa.expire = get32(cp);
  235.         cp += 4;
  236.         rrp->rdata.soa.minimum = get32(cp);
  237.         cp += 4;
  238.         break;
  239.     case TYPE_TXT:
  240.         /* Just stash */
  241.         rrp->rdata.data = mallocw(rrp->rdlength);
  242.         memcpy(rrp->rdata.data,cp,rrp->rdlength);
  243.         cp += rrp->rdlength;
  244.         break;
  245.     default:
  246.         /* Ignore */
  247.         cp += rrp->rdlength;
  248.         break;
  249.     }
  250.     free(name);
  251.     return cp;
  252. }
  253.  
  254. /* Convert a compressed domain name to the human-readable form */
  255. static int
  256. dn_expand(msg,eom,compressed,full,fullen)
  257. char *msg;        /* Complete domain message */
  258. char *eom;
  259. char *compressed;    /* Pointer to compressed name */
  260. char *full;        /* Pointer to result buffer */
  261. int fullen;        /* Length of same */
  262. {
  263.     unsigned int slen;    /* Length of current segment */
  264.     register char *cp;
  265.     int clen = 0;    /* Total length of compressed name */
  266.     int indirect = 0;    /* Set if indirection encountered */
  267.     int nseg = 0;        /* Total number of segments in name */
  268.  
  269.     cp = compressed;
  270.     for(;;){
  271.         slen = uchar(*cp++);    /* Length of this segment */
  272.         if(!indirect)
  273.             clen++;
  274.         if((slen & 0xc0) == 0xc0){
  275.             if(!indirect)
  276.                 clen++;
  277.             indirect = 1;
  278.             /* Follow indirection */
  279.             cp = &msg[((slen & 0x3f)<<8) + uchar(*cp)];
  280.             slen = uchar(*cp++);
  281.         }
  282.         if(slen == 0)    /* zero length == all done */
  283.             break;
  284.         fullen -= slen + 1;
  285.         if(fullen < 0)
  286.             return -1;
  287.         if(!indirect)
  288.             clen += slen;
  289.         while(slen-- != 0)
  290.             *full++ = *cp++;
  291.         *full++ = '.';
  292.         nseg++;
  293.     }
  294.     if(nseg == 0){
  295.         /* Root name; represent as single dot */
  296.         *full++ = '.';
  297.         fullen--;
  298.     }
  299.     *full++ = '\0';
  300.     fullen--;
  301.     return clen;    /* Length of compressed message */
  302. }
  303.  
  304.  
  305.  
  306. #ifdef DSERVER
  307.  
  308. /* Most of this code is based on the DNS server in PA0GRI's 910828
  309.  * Ported to the current NOS code by Johan. K. Reinalda, WG7J
  310.  * for version and bug/feature info, see domain.c
  311.  */
  312.  
  313. static char *
  314. dn_compress(cp,name)
  315. char *cp, *name;
  316. {
  317.     int len,dlen;
  318.     char *cp1;
  319.     dlen = strlen(name);
  320.     for(;;){
  321.         /* Look for next dot */
  322.         cp1 = strchr(name,'.');
  323.         if(cp1 != NULLCHAR)
  324.             len = cp1-name;    /* More to come */
  325.         else
  326.             len = dlen;    /* Last component */
  327.         *cp++ = len;        /* Write length of component */
  328.         if(len == 0)
  329.             return cp;
  330.         /* Copy component up to (but not including) dot */
  331.         strncpy(cp,name,len);
  332.         cp += len;
  333.         if(cp1 == NULLCHAR){
  334.             *cp++ = 0;    /* Last one; write null and finish */
  335.             return cp;
  336.         }
  337.         name += len+1;
  338.         dlen -= len+1;
  339.     }
  340. }
  341.  
  342. /* Translate a resource record from host format to network format */
  343. static char *
  344. htonrr(rr,buffer)
  345. struct rr *rr;
  346. char *buffer;
  347. {
  348.     struct rr *rrp;
  349.     char *cp, *p;
  350.     int i, len;
  351.  
  352.     cp = buffer;
  353.     for(rrp = rr; rrp != NULLRR; rrp = rrp->next) {
  354. #ifdef notdef
  355.         i = strlen(rrp->name);
  356.         if(rrp->name[i-1] != '.'
  357.            && rrp->origin != NULLCHAR) {
  358.             p = mallocw(i + strlen(rrp->origin) + 2);
  359.             sprintf(p,"%s.%s",rrp->name,rrp->origin);
  360.             cp = dn_compress(cp,p);
  361.             free(p);
  362.         } else
  363. #endif
  364.             cp = dn_compress(cp,rrp->name);
  365.         cp = put16(cp,rrp->type);
  366.         cp = put16(cp,rrp->class);
  367.         cp = put32(cp,rrp->ttl);
  368. #ifdef notdef
  369.         /* The length doesn't seem to be right for all types ! */
  370.         cp = put16(cp,rrp->rdlength);
  371. #endif
  372.         p = cp;     /* This is where the length goes ! */
  373.         cp += 2;    /* Save the space for lenght field */
  374.  
  375.         switch(rrp->type) {
  376.         case TYPE_A:
  377.             cp = put32(cp,rrp->rdata.addr);
  378.             break;
  379.         case TYPE_SOA:
  380.             cp = dn_compress(cp,rrp->rdata.soa.mname);
  381.             cp = dn_compress(cp,rrp->rdata.soa.rname);
  382.             cp = put32(cp,rrp->rdata.soa.serial);
  383.             cp = put32(cp,rrp->rdata.soa.refresh);
  384.             cp = put32(cp,rrp->rdata.soa.retry);
  385.             cp = put32(cp,rrp->rdata.soa.expire);
  386.             cp = put32(cp,rrp->rdata.soa.minimum);
  387.             break;
  388.         case TYPE_HINFO:
  389.             *cp++ = len = strlen(rrp->rdata.hinfo.cpu); 
  390.             strncpy(cp,rrp->rdata.hinfo.cpu,len); 
  391.             cp += len;
  392.             *cp++ = len = strlen(rrp->rdata.hinfo.os);
  393.             strncpy(cp,rrp->rdata.hinfo.os,len); 
  394.             cp += len;
  395.             break;
  396.         case TYPE_MX:
  397.             cp = put16(cp,rrp->rdata.mx.pref); 
  398.             cp = dn_compress(cp,rrp->rdata.mx.exch);
  399.             break;
  400.         case TYPE_CNAME:
  401.         case TYPE_MB:
  402.         case TYPE_MG:
  403.         case TYPE_MR:
  404.         case TYPE_NS:
  405.         case TYPE_PTR:
  406.             cp = dn_compress(cp,rrp->rdata.data);
  407.             break;
  408.         case TYPE_MINFO:    /* Unsupported type */
  409.         cp = dn_compress(cp,rrp->rdata.minfo.rmailbx);
  410.         cp = dn_compress(cp,rrp->rdata.minfo.emailbx);
  411.         case TYPE_MD:       /* Unsupported type */
  412.         case TYPE_MF:       /* Unsupported type */
  413.         case TYPE_NULL:     /* Unsupported type */
  414.         case TYPE_WKS:      /* Unsupported type */
  415.             cp = dn_compress(cp,rrp->rdata.data);
  416.             break;
  417.         case TYPE_TXT:
  418.         default:
  419.             cp = put16(cp,rrp->rdlength);
  420.             for(i=0 ; i < rrp->rdlength ; i++)
  421.                 *cp++ = rrp->rdata.data[i];
  422.             break;
  423.         }
  424.         /* Calculate the lenght of the RR */
  425.         len = cp - p - 2;
  426.         put16(p,len);       /* and set it */
  427.     }
  428.     return cp;
  429. }
  430.  
  431. int
  432. htondomain(dhdr,buffer,buflen)
  433. struct dhdr *dhdr;
  434. char *buffer;    /* Area for query */
  435. int16 buflen;    /* Length of same */
  436. {
  437.     char *cp;
  438.     struct rr *rrp;
  439.     int16 parameter;
  440.     int i, count;
  441.  
  442.     cp = buffer;
  443.     cp = put16(cp,dhdr->id);    
  444.     if(dhdr->qr)
  445.         parameter = 0x8000;
  446.     else
  447.         parameter = 0;
  448.     parameter |= (dhdr->opcode & 0x0f) << 11;
  449.     if(dhdr->aa)
  450.         parameter |= DOM_AUTHORITY;
  451.     if(dhdr->tc)
  452.         parameter |= DOM_TRUNC;
  453.     if(dhdr->rd)
  454.         parameter |= DOM_DORECURSE;
  455.     if(dhdr->ra)
  456.         parameter |= DOM_CANRECURSE;
  457.     parameter |= (dhdr->rcode & 0x0f);
  458.     cp = put16(cp,parameter);
  459.     cp = put16(cp,dhdr->qdcount);
  460.     cp = put16(cp,dhdr->ancount);
  461.     cp = put16(cp,dhdr->nscount);
  462.     cp = put16(cp,dhdr->arcount);
  463.     if((count = dhdr->qdcount) > 0) {
  464.         rrp = dhdr->questions;
  465.         for(i = 0; i < count; i++) {
  466.             cp = dn_compress(cp,rrp->name);
  467.             cp = put16(cp,rrp->type);
  468.             cp = put16(cp,rrp->class);
  469.             rrp = rrp->next;
  470.         }
  471.     }
  472.     if((count = dhdr->ancount) > 0) {
  473.         rrp = dhdr->answers;
  474.         for(i = 0; i < count; i++) {
  475.             cp = htonrr(rrp,cp);
  476.             rrp = rrp->next;
  477.         }
  478.     }
  479.     if((count = dhdr->nscount) > 0) {
  480.         rrp = dhdr->authority;
  481.         for(i = 0; i < count; i++) {
  482.             cp = htonrr(rrp,cp);
  483.             rrp = rrp->next;
  484.         }
  485.     }
  486.     if((count = dhdr->arcount) > 0) {
  487.         rrp = dhdr->additional;
  488.         for(i = 0; i < count; i++) {
  489.             cp = htonrr(rrp,cp);
  490.             rrp = rrp->next;
  491.         }
  492.     }
  493.     return cp - buffer;
  494. }
  495.  
  496.  
  497. #endif
  498.  
  499.